package ch.nostromo.tiffanys.engines.tiffanys.board.pieces;

import ch.nostromo.tiffanys.engines.tiffanys.board.TiffanysBoard;
import ch.nostromo.tiffanys.game.board.Board;

public abstract class TiffanysPiece {

  public static boolean[] LEGALBOARD = new boolean[120];

  public static boolean initialized = false;

  public static void initialize() {
    if (initialized) {
      return;
    }

    initializeLegalBoard();
  }

  private static void initializeLegalBoard() {

    // First, all fields are "legal"
    for (int i = 0; i < 120; i++) {
      LEGALBOARD[i] = true;
    }
    // Overwrite some fields as "void"
    for (int i = 0; i <= 19; i++) {
      LEGALBOARD[i] = false;
    }
    for (int i = 20; i <= 90; i += 10) {
      LEGALBOARD[i] = false;
    }
    for (int i = 29; i <= 99; i += 10) {
      LEGALBOARD[i] = false;
    }
    for (int i = 100; i <= 119; i++) {
      LEGALBOARD[i] = false;
    }

  }

  public static short checkDirection(int myPosition, int direction, boolean[] validMoveFields, int[] enemyValues) {
    short result = 0;
    while (true) {
      int toField = myPosition + ((result + 1) * direction);
      if (!validMoveFields[toField]) {
        return result;
      } else {
        result++;
        if (enemyValues[toField] != 0) {
          return result;
        } 
      }
    }
  }

  public static short checkHitDirection( int myPosition, int direction, boolean[] validMoveFields, int[] enemyValues) {
    short result = 0;
    while (true) {
      int toField = myPosition + ((result + 1) * direction);
      if (!validMoveFields[toField]) {
        return 0;
      } else {
        result++;
        if (enemyValues[toField] != 0) {
          return result;
        }  
      }
    }

  }

  public static short checkEnemiesInDirection(int board[], int myPosition, int enemyColor, int direction) {
    short result = 0;
    while (true) {
      int toField = myPosition + ((result + 1) * direction);
      if (!LEGALBOARD[toField]) {
        return result;
      }

      if ((Board.EMPTY_FIELD & board[toField]) != 0) {
        result++;
      } else {
        if ((enemyColor & board[toField]) != 0) {
          result++;
          return result;
        } else {
          return 8;
        }
      }

    }

  }

  public static long getEnemiesInDirection(long board[], int myPosition, int enemyColor, int direction) {
    int counter = 0;
    while (true) {
      int toField = myPosition + ((counter + 1) * direction);
      if (!LEGALBOARD[toField]) {
        return 0;
      }

      if ((Board.EMPTY_FIELD & board[toField]) != 0) {
        counter++;
      } else {
        if ((enemyColor & board[toField]) != 0) {
          return board[toField];
        } else {
          return 0;
        }
      }

    }

  }

  public static boolean isKingAttacked(long[] board, long posp, int currentColor) {
    int enemyColor = TiffanysBoard.invertColor(currentColor);
    long fieldContentToCheck = 0;

    int pos = (int) posp;

    // Check for Knight Attacks
    if ((board[pos + 19] & Board.PIECE_KNIGHT) != 0 && (board[pos + 19] & enemyColor) != 0) {
      return true;
    }
    if ((board[pos + 21] & Board.PIECE_KNIGHT) != 0 && (board[pos + 21] & enemyColor) != 0) {
      return true;
    }
    if ((board[pos + 12] & Board.PIECE_KNIGHT) != 0 && (board[pos + 12] & enemyColor) != 0) {
      return true;
    }
    if ((board[pos - 8] & Board.PIECE_KNIGHT) != 0 && (board[pos - 8] & enemyColor) != 0) {
      return true;
    }
    if ((board[pos - 19] & Board.PIECE_KNIGHT) != 0 && (board[pos - 19] & enemyColor) != 0) {
      return true;
    }
    if ((board[pos - 21] & Board.PIECE_KNIGHT) != 0 && (board[pos - 21] & enemyColor) != 0) {
      return true;
    }
    if ((board[pos - 12] & Board.PIECE_KNIGHT) != 0 && (board[pos - 12] & enemyColor) != 0) {
      return true;
    }
    if ((board[pos + 8] & Board.PIECE_KNIGHT) != 0 && (board[pos + 8] & enemyColor) != 0) {
      return true;
    }

    // Check for diagonal Attacks
    fieldContentToCheck = getEnemiesInDirection(board, pos, enemyColor, 11);
    if (fieldContentToCheck > 0 && ((fieldContentToCheck & Board.PIECE_BISHOP) != 0 || (fieldContentToCheck & Board.PIECE_QUEEN) != 0)) {
      return true;
    }
    fieldContentToCheck = getEnemiesInDirection(board, pos, enemyColor, -11);
    if (fieldContentToCheck > 0 && ((fieldContentToCheck & Board.PIECE_BISHOP) != 0 || (fieldContentToCheck & Board.PIECE_QUEEN) != 0)) {
      return true;
    }
    fieldContentToCheck = getEnemiesInDirection(board, pos, enemyColor, 9);
    if (fieldContentToCheck > 0 && ((fieldContentToCheck & Board.PIECE_BISHOP) != 0 || (fieldContentToCheck & Board.PIECE_QUEEN) != 0)) {
      return true;
    }
    fieldContentToCheck = getEnemiesInDirection(board, pos, enemyColor, -9);
    if (fieldContentToCheck > 0 && ((fieldContentToCheck & Board.PIECE_BISHOP) != 0 || (fieldContentToCheck & Board.PIECE_QUEEN) != 0)) {
      return true;
    }

    fieldContentToCheck = getEnemiesInDirection(board, pos, enemyColor, 1);
    if (fieldContentToCheck > 0 && ((fieldContentToCheck & Board.PIECE_ROOK) != 0 || (fieldContentToCheck & Board.PIECE_QUEEN) != 0)) {
      return true;
    }

    fieldContentToCheck = getEnemiesInDirection(board, pos, enemyColor, -1);
    if (fieldContentToCheck > 0 && ((fieldContentToCheck & Board.PIECE_ROOK) != 0 || (fieldContentToCheck & Board.PIECE_QUEEN) != 0)) {
      return true;
    }

    fieldContentToCheck = getEnemiesInDirection(board, pos, enemyColor, 10);
    if (fieldContentToCheck > 0 && ((fieldContentToCheck & Board.PIECE_ROOK) != 0 || (fieldContentToCheck & Board.PIECE_QUEEN) != 0)) {
      return true;
    }

    fieldContentToCheck = getEnemiesInDirection(board, pos, enemyColor, -10);
    if (fieldContentToCheck > 0 && ((fieldContentToCheck & Board.PIECE_ROOK) != 0 || (fieldContentToCheck & Board.PIECE_QUEEN) != 0)) {
      return true;
    }

    // Check for pawn Attacks
    if (currentColor == Board.OWNER_WHITE) {
      if ((board[pos + 11] & Board.PIECE_PAWN) != 0 && (board[pos + 11] & enemyColor) != 0) {
        return true;
      }

      if ((board[pos + 9] & Board.PIECE_PAWN) != 0 && (board[pos + 9] & enemyColor) != 0) {
        return true;
      }

    } else {
      if ((board[pos - 11] & Board.PIECE_PAWN) != 0 && (board[pos - 11] & enemyColor) != 0) {
        return true;
      }

      if ((board[pos - 9] & Board.PIECE_PAWN) != 0 && (board[pos - 9] & enemyColor) != 0) {
        return true;
      }

    }

    // Check for King Attacks
    if ((board[pos + 9] & Board.PIECE_KING) != 0 && (board[pos +9] & enemyColor) != 0 ) {
      return true;
    }
    if ((board[pos + 10] & Board.PIECE_KING) != 0 && (board[pos +10] & enemyColor) != 0 ) {
      return true;
    }
    if ((board[pos + 11] & Board.PIECE_KING) != 0 && (board[pos +11] & enemyColor) != 0 ) {
      return true;
    }
    if ((board[pos + 1] & Board.PIECE_KING) != 0 && (board[pos +1] & enemyColor) != 0 ) {
      return true;
    }
    if ((board[pos - 1] & Board.PIECE_KING) != 0 && (board[pos -1] & enemyColor) != 0 ) {
      return true;
    }
    if ((board[pos - 9] & Board.PIECE_KING) != 0) {
      return true;
    }
    if ((board[pos - 10] & Board.PIECE_KING) != 0) {
      return true;
    }
    if ((board[pos - 11] & Board.PIECE_KING) != 0) {
      return true;
    }

    return false;

  }

}